package io.jft.doll.ui.recharge

import android.annotation.SuppressLint
import android.arch.lifecycle.ViewModelProviders
import android.databinding.Observable
import android.databinding.ObservableField
import android.os.Bundle
import android.view.View
import com.alibaba.android.arouter.facade.annotation.Route
import com.alibaba.android.arouter.launcher.ARouter
import com.alibaba.android.vlayout.LayoutHelper
import com.alibaba.android.vlayout.layout.GridLayoutHelper
import com.alipay.sdk.app.PayTask
import com.g.base.extend.*
import com.g.base.help.ProgressDialog
import com.g.base.room.entity.UserEntity
import com.g.base.room.repository.Status
import com.g.base.router.RouteExtras
import com.g.base.ui.BaseActivity
import com.g.base.ui.recyclerView.MultiTypeAdapter
import com.g.base.ui.recyclerView.setupRecyclerView
import com.tencent.mm.opensdk.modelbase.BaseResp
import com.tencent.mm.opensdk.modelpay.PayReq
import io.jft.doll.R
import io.jft.doll.api.weChatApi
import io.jft.doll.databinding.ActivityRechargeBinding
import io.jft.doll.event.WX_APP_ID
import io.jft.doll.event.WxPayEvent
import io.jft.doll.model.viewModel.UserViewModel
import io.jft.doll.room.entity.remote.MakeChargeREntity
import io.jft.doll.room.entity.remote.SuggestChargeREntity
import io.jft.doll.router.RouterPage
import io.jft.doll.ui.recharge.bind.ChargeButtonBind
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode

/**
 * Created by G on 2017/12/1 0001.
 */
@Route(path = RouterPage.RechargeActivity, extras = RouteExtras.NeedOauth)
class RechargeActivity : BaseActivity<ActivityRechargeBinding>() {
    override var hasToolbar: Boolean = true

    private val userViewModel by lazy { ViewModelProviders.of(this).get(UserViewModel::class.java) }
    private val progressDialog by lazy { ProgressDialog() }
    private lateinit var payParams: MakeChargeREntity

    private lateinit var fixedChargeAdapter: MultiTypeAdapter
    private val currentSelectFixedChargeIndex by lazy { ObservableField(-1) }
    var recommendChargeData = SuggestChargeREntity()
    val currentInputCharge = ObservableField("")
    val userRemainingSum = ObservableField("")


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_recharge)
        initView()
        getData()

        currentInputCharge.addOnPropertyChangedCallback(object : Observable.OnPropertyChangedCallback() {
            override fun onPropertyChanged(sender: Observable?, propertyId: Int) {
                var hasSet = false
                recommendChargeData.suggest.forEachIndexed { index, it ->
                    if (it.coin == currentInputCharge.get()) {
                        currentSelectFixedChargeIndex.set(index)
                        hasSet = true
                    }
                }
                if (!hasSet)
                    currentSelectFixedChargeIndex.set(-1)
            }
        })
    }

    override fun onReload() {
        getData()
    }

    override fun onTokenChange(data: UserEntity?) {
        if (data == null) {
            showNeedOauth()
        } else {
            getData()
        }
    }

    private fun initView() {
        toolbar.title = "充值中心"
        toolbar.setNavigationIcon(R.drawable.ic_arrow_back_toolbar_24dp)
        toolbar.setNavigationOnClickListener { finishAfterTransition() }

        toolbar.inflateMenu(R.menu.bills)
        toolbar.setOnMenuItemClickListener {
            ARouter.getInstance().build(RouterPage.BillsActivity).navigation(this)
            true
        }
    }

    @SuppressLint("CheckResult")
    private fun getData() {
        userViewModel.getSuggestChargeRemainingSumZip(this)
                .take(1)
                .subscribe(
                        {
                            if (it.first.status == Status.Error || it.second.status == Status.Error) {
                                showError(it.first.error?.message ?: it.second.error?.message)
                            } else {
                                userRemainingSum.set(it.first.data!!)
                                userViewModel.changeRemain(it.first.data!!)
                                recommendChargeData = it.second.data!!
                                contentView.data = this
                                setRecyclerView()
                                showContentView()
                            }
                        },
                        {
                            showError()
                        }
                )
    }

    private fun setRecyclerView() {
        fixedChargeAdapter = setupRecyclerView(contentView.recyclerView)
        fixedChargeAdapter.renderItems.addAll(
                recommendChargeData.suggest.mapIndexed { index, it ->
                    ChargeButtonBind(currentSelectFixedChargeIndex, index, it.coin, it.money.round(2))
                            .apply {
                                setOnClickListener { _ ->
                                    contentView.remaining.requestFocus()
                                    contentView.otherExcess.showKeyboard(false)
                                    currentInputCharge.set(it.coin)
                                }
                            }
                }
        )
        fixedChargeAdapter.layoutHelpers = arrayListOf(GridLayoutHelper(2, 6, 16.dp(), 24.dp()) as LayoutHelper)
        fixedChargeAdapter.notifyDataSetChanged()
    }

    /**
     * 获取支付参数
     */
    fun onPayClick(view: View) {
        val charge = (currentInputCharge.get() ?: "0").toLongOrNull()
        if (charge == null || charge < recommendChargeData.charge.minCharge) {
            toast("最低充值 ${recommendChargeData.charge.minCharge}娃娃币")
            return
        }
        payParams = MakeChargeREntity()
        //0微信 1支付宝
        userViewModel.makeCharge(currentInputCharge.get()!!, if (view.id == R.id.alipay) "1" else "0")
                .resultNotNull()
                .observeExOnce(this) {
                    when (it.status) {
                        Status.Loading -> {
                            progressDialog.setStart("正在获取支付参数中...")
                        }
                        Status.Content -> {
                            payParams = it.data!!
                            progressDialog.dialog?.setCancelable(true)
                            if (payParams.type == 1) {
                                invokeAlipay()
                            } else {
                                invokeWeChatPay()
                            }
                        }
                        Status.Error -> {
                            progressDialog.setFiled("获取支付参数失败 无法支付~") {
                                it.dismiss(true)
                            }
                        }
                    }
                }
    }

    /**
     * 通过支付宝支付
     */
    @SuppressLint("CheckResult")
    private fun invokeAlipay() {
        progressDialog.dialog?.contentText = "正在调用支付宝,可按返回键取消~"
        io.reactivex.Observable.create<Map<String, String>> { ob ->
            ob.onNext(PayTask(this).payV2(payParams.aliPayParm, false))
        }
                .mainIoSchedulers()
                .subscribe(
                        { result ->
                            when (result["resultStatus"]) {
                                "9000", "8000", "6004", "5000" -> {
                                    asyncPayResult(payParams.orderNo)
                                }
                                else -> {
                                    progressDialog.setFiled(result["msg"]
                                            ?: "未知原因 支付失败 Code:${result["resultStatus"]}")
                                    {
                                        it.dismiss(true)
                                    }
                                }
                            }
                        },
                        {
                            progressDialog.setFiled("支付宝支付失败") {
                                it.dismiss(true)
                            }
                        }
                )
    }

    /**
     * 通过微信支付
     */
    private fun invokeWeChatPay() {
        if (!weChatApi.isWXAppInstalled) {
            progressDialog.setFiled("请先安装微信") {
                it.dismiss(true)
            }
            return
        }
        var invokeSucceed = false
        try {
            progressDialog.dialog?.contentText = "正在调用微信支付,可按返回键取消~"
            val payReq = PayReq()
            val wxPayParm = payParams.wxPayParm
            payReq.appId = WX_APP_ID
            payReq.partnerId = wxPayParm.partnerid
            payReq.prepayId = wxPayParm.prepayid
            payReq.nonceStr = wxPayParm.noncestr
            payReq.timeStamp = wxPayParm.timestamp
            payReq.packageValue = wxPayParm.packageX
            payReq.sign = wxPayParm.sign
            invokeSucceed = weChatApi.sendReq(payReq)
        } finally {
            if (!invokeSucceed)
                progressDialog.setFiled("使用微信支付失败") {
                    it.dismiss(true)
                }
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onWeChatCallBack(wxPayEvent: WxPayEvent) {
        val data = wxPayEvent.data
        if (data.errCode == BaseResp.ErrCode.ERR_OK) {
            asyncPayResult(payParams.orderNo)
        } else {
            progressDialog.setFiled("使用微信支付失败 Code: ${data.errCode}") {
                it.dismiss(true)
            }
        }
    }

    /**
     * 同步支付状态
     * 订单状态  0-未知  1-错误  2-成功
     */
    @SuppressLint("CheckResult")
    private fun asyncPayResult(orderId: String, retry: Int = 5) {
        progressDialog.dialog?.titleText = "获取支付结果中,请勿关闭"
        userViewModel.asyncChargeStatus(orderId)
                .resultNotNull()
                .toObservable(this)
                .retryWithDelay(3, 1000L)
                .subscribe(
                        {
                            when {
                                it.status == Status.Content -> {
                                    //同步余额
                                    userViewModel.changeRemain(it.data!!.remaining)
                                    userRemainingSum.set(it.data!!.remaining)
                                    when {
                                        it.data!!.status == 0 -> if (retry == 0) {
                                            progressDialog.setFiled("暂时无法查询到交易结果!") {
                                                it.dismiss(true)
                                            }
                                        } else {
                                            asyncPayResult(orderId, retry - 1)
                                        }
                                        it.data!!.status == 1 -> progressDialog.setFiled("支付失败") {
                                            it.dismiss(true)
                                        }
                                        else -> progressDialog.setSucceed("支付成功") {
                                            it.dismiss(true)
                                        }
                                    }
                                }
                                else -> progressDialog.setFiled("暂时无法查询到交易结果!") {
                                    it.dismiss(true)
                                }
                            }
                        },
                        {
                            progressDialog.setFiled("暂时无法查询到啊交易结果,请稍后查看我的余额!") {
                                it.dismiss(true)
                            }
                        }
                )
    }
}